<?php
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.gxgyl.com All rights reserved.

// +----------------------------------------------------------------------
// | Author: Liuyu
// +----------------------------------------------------------------------
declare (strict_types = 1);

namespace app\store\service\order;

use app\common\enum\order\export\ExportStatus as ExportStatusEnum;
use app\common\library\helper;
use app\common\service\BaseService;use app\store\model\order\Export as ExportModel;use app\store\model\shiyao\PayLog as ProjectPayModel;use cores\exception\BaseException;use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;

/**
 * 服务层：订单导出Excel
 * Class Export
 * @package app\store\service\order
 */
class Export extends BaseService {
	// 表格文件标题名称
	private $title = '订单导出结果';

	/**
	 * 执行订单导出excel
	 * @param array $param
	 * @return bool
	 * @throws BaseException
	 */
	public function exportOrder(array $param) {
		$param['columns'] = ['id', 'project_name', 'center_name', 'code', 'cycle', 'category', 'money', 'pay_time', 'create_time'];
		// 根据条件查询订单列表
		$orderList = $this->getOrderList($param);
		// 格式化生成表格数据
		$excelList = $this->getExcelList($orderList, $param['columns']);
		// 获取导出的记录列名集
		$columns = $this->getColumns($param['columns']);
		// 输出并写入到excel文件
		$filePath = $this->outputExcel($columns, $excelList);
		// 新增订单导出记录
		$this->record($param, $filePath);
		return $filePath;
	}

	/**
	 * 根据条件查询订单列表
	 * @param array $param
	 * @return mixed
	 * @throws BaseException
	 */
	private function getOrderList(array $param) {
		// 根据条件查询订单列表
		$model = new ProjectPayModel;
		$orderList = $model->getListAll($param);
		if (!$orderList) {
			throwError('很抱歉，没有查询到补助数据');
		}
		return $orderList;
	}

	/**
	 * 输出并写入到excel文件
	 * @param array $columns 列名
	 * @param array $excelList 表格内容
	 * @return string
	 * @throws BaseException
	 */
	private function outputExcel(array $columns, array $excelList): string {
		// 生成工作表
		$spreadsheet = new Spreadsheet();
		$sheet = $spreadsheet->getActiveSheet()->setTitle($this->title);
		// 列宽
		$sheet->getDefaultColumnDimension()->setWidth(24);
		// 默认行高
		$sheet->getDefaultRowDimension()->setRowHeight(20);
		// 字体加粗(第一行)
		$sheet->getStyle('1')->getFont()->setBold(true);
		// 写入标题数据
		foreach ($columns as $key => $val) {
			$sheet->setCellValueByColumnAndRow($key + 1, 1, $val);
		}
		// 写入内容数据
		foreach ($excelList as $key => $item) {
			$row = $key + 2;
			foreach (array_values($item) as $k => $val) {
				$sheet->setCellValueByColumnAndRow($k + 1, $row, $val);
			}
		}
		// 生成文件路径
		$fileName = 'pay-' . time() . '.xlsx';
		$filePath = $this->getExportPath();
		// 保存到文件
		try {
			$writer = new Xlsx($spreadsheet);
			$writer->save(public_path() . $filePath . $fileName);
		} catch (\PhpOffice\PhpSpreadsheet\Writer\Exception $e) {
			throwError($e->getMessage());
		}
		return $filePath . $fileName;
	}

	/**
	 * 获取导出的文件夹路径
	 * @return string
	 */
	private function getExportPath(): string {
		$filePath = 'downloads/' . $this->getStoreId() . '/';
		!is_dir($filePath) && mkdir($filePath, 0755, true);
		return $filePath;
	}

	/**
	 * 写入订单导出记录
	 * @param array $param
	 * @param string $filePath
	 * @return void
	 */
	private function record(array $param, string $filePath): void {
		// 生成记录数据
		$data = [
			'file_path' => $filePath,
			'status' => ExportStatusEnum::COMPLETED,
			'store_id' => $this->getStoreId(),
		];
		// 起止时间
		if (!empty($param['betweenTime'])) {
			$times = between_time($param['betweenTime']);
			$data['start_time'] = $times['start_time'];
			$data['end_time'] = $times['end_time'];
		}
		// 新增记录
		$model = new ExportModel;
		$model->add($data);
	}

	/**
	 * 获取导出的记录列名集
	 * @param array $onlyFields
	 * @return array
	 */
	private function getColumns(array $onlyFields): array {
		return array_values(helper::pick($this->dictionary(), $onlyFields));
	}

	/**
	 * 订单记录字典
	 * @return string[]
	 */
	private function dictionary(): array {
		return [
			'id' => 'ID',
			'project_name' => '项目名称',
			'center_name' => '中心',
			'code' => '受试者编号',
			'cycle' => '访视周期',
			'category' => '补助类型',
			'money' => '补助金额',
			'pay_time' => '补助日期',
			'create_time' => '提交日期',

		];
	}

	/**
	 * 格式化生成表格数据
	 * @param array $orderList
	 * @param array $onlyFields
	 * @return array
	 */
	private function getExcelList(array $orderList, array $onlyFields): array {
		// 获取订单表格数据
		$excelList = $this->getOrderDataForExcel($orderList);
		// 仅输出用户设置的字段
		$data = [];
		foreach ($excelList as $item) {
			$data[] = helper::pick($item, $onlyFields);
		}
		return $data;
	}

	/**
	 * 获取订单列表数据(用于生成Excel)
	 * @param $orderList
	 * @return array
	 */
	private function getOrderDataForExcel($orderList): array {
      
		// 表格内容
		$dataArray = [];
		foreach ($orderList as $order) {
			$dataArray[] = [
				'id' => $this->filterValue($order['id']),
				'project_name' => $this->filterValue($order['project']['project_name']),
				'center_name' => $this->filterValue($order['center']['center_name']),
				'code' => $this->filterValue($order['testee']['code']),
				'cycle' => $this->filterValue($this->filterGoodsInfo($order)),
				'category' => $this->filterValue($order['category_name']),
				'money' => $this->filterValue($order['money']),
				'pay_time' => $this->filterValue($order['pay_time']),
				'create_time' => $this->filterValue($order['create_time']),

			];
		}
		return $dataArray;
	}

	/**
	 * 格式化商品信息
	 * @param $order
	 * @return string
	 */
	private function filterGoodsInfo($order): string {

		if ($order['is_out']) {
			$date = $order['out_time'];
			$content = "　计划外访视：{$date}\n";
		} else {
			$content = $order['visit_cycle'];
		}

		return $content;
	}

	/**
	 * 表格值过滤
	 * @param $value
	 * @return string
	 */
	private function filterValue($value): string {
		return "\t{$value}\t";
	}
}